/**
 * Represents the Fat Albert character
 * 
 * @author SNelson
 * 
 */
public class FatAlbert extends Thread implements Schedulable
{
	/**
	 * The vending machine that Fat Albert visits
	 */
	private final VendingMachine machine;
	/**
	 * The scheduler that notifies us of time events
	 */
	private final Scheduler scheduler;

	/**
	 * The hours in the current day that Fat Albert will attempt to gorge
	 * himself
	 */
	private int[] hoursToEat = null;

	/**
	 * The number of times to eat when Fat Albert eats
	 */
	private int timesToEat = 0;

	/**
	 * Whether or not the Fat Albert thread should stop
	 */
	private boolean stop = false;

	/**
	 * The indent for print statements for Fat Albert
	 */
	public static final String INDENT = "            ";
	/**
	 * The name to use for printing
	 */
	public static final String NAME = "Fat Albert";

	/**
	 * Constructor
	 * 
	 * @param scheduler
	 *            The scheduler that notifies us of time events
	 * @param machine
	 *            The vending machine that Fat Albert visits
	 */
	public FatAlbert(Scheduler scheduler, VendingMachine machine)
	{
		this.scheduler = scheduler;
		scheduler.addSchedulable(this);
		this.machine = machine;
		setName(NAME);
	}

	/**
	 * Called when a new day begins
	 * 
	 * @param day
	 *            The numeric day in the simulation
	 */
	@Override
	public void onNewDay(int day)
	{
		int timesToEat = (int) (Math.random() * 2 + 2);
		hoursToEat = new int[timesToEat];
		for (int i = 0; i < hoursToEat.length; i++)
			hoursToEat[i] = (int) (Math.random() * 23);
	}

	/**
	 * Called when a new hour begins
	 * 
	 * @param day
	 *            The numeric day in the simulation
	 * @param hour
	 *            The hour of the day
	 */
	@Override
	public void onHour(int day, int hour)
	{
		boolean isTimeToEat = false;
		for (int hourToEat : hoursToEat)
		{
			if (hourToEat == hour)
			{
				timesToEat++;
				isTimeToEat = true;
			}
		}
		if (isTimeToEat)
		{
			synchronized (this)
			{
				notifyAll();
			}
		}
	}

	/**
	 * Called when the simulation needs to end
	 */
	public synchronized void onSimulationEnd()
	{
		scheduler.removeSchedulable(this);
		stop = true;
		notifyAll();
	}

	/**
	 * Body of this thread
	 */
	@Override
	public void run()
	{
		while (!stop)
		{
			synchronized (this)
			{
				try
				{
					wait();
				}
				catch (InterruptedException e)
				{
					e.printStackTrace();
				}

				if (stop)
				{
					return;
				}

				while (timesToEat > 0)
				{
					VendingMachineTransaction.Builder builder = new VendingMachineTransaction.Builder(
						machine);
					VendingMachineTransaction transaction = builder
						.doSomething(new Runnable()
						{
							@Override
							public void run()
							{
								print("Attempting to purchase a cookie");
							}
						}).purchaseCookie().build();
					boolean success = machine.executeTransaction(transaction);
					builder = new VendingMachineTransaction.Builder(machine);
					transaction = builder.doSomething(new Runnable()
					{
						@Override
						public void run()
						{
							print("Attempting to purchase a candy");
						}
					}).purchaseCandy().build();
					boolean success2 = machine.executeTransaction(transaction);
					if (success && success2)
					{
						print("Hey, hey hey!");
					}
					else if (success)
					{
						print("At least I got a Cookie");
					}
					else if (success2)
					{
						print("At least I got a Candy");
					}
					else
					{
						print("No food for me today");
					}
					timesToEat--;
				}
			}
		}
	}

	/**
	 * Prints the given contents formatted for Fat Albert
	 * 
	 * @param contents
	 *            The contents to print
	 */
	private void print(String contents)
	{
		System.out.println(INDENT + scheduler.getFormattedTime() + " "
			+ getName() + ": " + contents);
	}
}
